package com.lzk.basic.service.impl;

import com.lzk.basic.excption.BusinessException;
import com.lzk.basic.service.IVerifyCodeService;
import com.lzk.basic.util.StrUtils;
import com.lzk.basic.util.VerifyCodeUtils;
import com.lzk.basic.constants.RegisterConstant;
import com.lzk.user.domain.User;
import com.lzk.user.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UserMapper userMapper;

    /**
     * 图形验证码业务实现
     * @param key
     * @return
     */
    @Override
    public String getVerifyCode(String key) {
        //判断key是否为空
        if(StringUtils.isEmpty(key)){
            throw new BusinessException("参数为空");
        }
        //获取随机验证码
        String code = StrUtils.getComplexRandomString(4);
        //将验证码存放到redis，设置3分钟过期
        redisTemplate.opsForValue().set(key,code,3, TimeUnit.MINUTES);
        //把验证码的值合并到图片，使用Base64编码。并返回base64编码的字符串
        return VerifyCodeUtils.verifyCode(100,40,code);
    }

    /**
     * 手机验证码业务实现
     * @param map
     */
    @Override
    public void sendSmsCode(Map<String, String> map) {
        //1.校验 - 空值校验
        String imageCode = map.get("imageCode");
        String imageCodeKey = map.get("imageCodeKey");
        String phone = map.get("phone");
        if(StringUtils.isEmpty(phone)){
            throw new BusinessException("手机号不可为空");
        }
        if(StringUtils.isEmpty(imageCodeKey)){
            throw new BusinessException("请刷新页面重新获取图片验证码");
        }
        if(StringUtils.isEmpty(imageCode)){
            throw new BusinessException("图片验证码不能为空");
        }
        //2.校验 - 图片验证码校验
        //2.1.图片验证码是否过期
        Object obj = redisTemplate.opsForValue().get(imageCodeKey);
        if(obj == null){
            throw new BusinessException("图片验证码过期，请重新输入");
        }
        //2.2.图片验证码是否正确
        if(!obj.toString().equalsIgnoreCase(imageCode)){
            throw new BusinessException("图片验证码错误，请确认后重新输入");
        }
        //3.校验 - 手机号是否被注册
        User user = userMapper.loadByPhone(phone);
        if(user != null){
            throw new BusinessException("该手机已经注册，请直接登录!");
        }

        //redis存值格式：key[手机号+业务键] : value[验证码:时间戳]
        Object codeObj = redisTemplate.opsForValue().get(phone+RegisterConstant.REGISTER_CODE_PREFIX);
        String code = null;//手机验证码
        if(codeObj != null){//没有过期
            String codeStr = (String)codeObj;
            String time = codeStr.split(":")[1];
            //当前时间是Long类型 减去 手机验证码时间
            long intervalTime = System.currentTimeMillis() - Long.valueOf(time);
            if(intervalTime <= 1*60*1000){ //没过重发时间：1分钟
                throw new BusinessException("请勿重复发送!");
            }else{
                code = codeStr.split(":")[0];//重新获取验证码
            }
        }else{//第一次赋值验证码
            code = StrUtils.getComplexRandomString(4);
        }
        //将验证码数据添加到redis
        redisTemplate.opsForValue().set(phone+ RegisterConstant.REGISTER_CODE_PREFIX,
                code + ":" + System.currentTimeMillis(),3, TimeUnit.MINUTES);//存3分钟
        //发短信
        //SmsUtils.sendSms(phone, "你的验证码为：" + code + "，请在3分钟之内使用!" );  //有次数
        //测试使用
        System.out.println("你的验证码为：" + code + "，请在3分钟之内使用!");
    }

    /**
     * 微信绑定手机号验证码业务
     * @param map
     */
    @Override
    public void binderSmsCode(Map<String, String> map) {
        String phone = map.get("phone");
        //校验
        if(StringUtils.isEmpty(phone)){
            throw new BusinessException("手机号不能为空!");
        }
        //判断是否第一次发送请求，或者验证码过期
        Object value = redisTemplate.opsForValue().get(phone + RegisterConstant.WXBINDER_CODE_PREFIX);
        //验证码
        String code = null;
        //如果取不到，没有发送过，获取过期了， 直接生成一个新的验证码保存到redis
        if(value==null){
            code = StrUtils.getComplexRandomString(4);
        }else{//取到，则判断是否超过一分钟
            //存入redis时间
            String redisTime = value.toString().split(":")[1];
            Long time = Long.valueOf(redisTime);
            //如果没有超过一分钟
            if(System.currentTimeMillis()-time<1*60*1000){
                throw new BusinessException("一分钟内请勿重复发送！");
            }else{//超过一分钟，刷新过期时间
                code = value.toString().split(":")[0];
            }
        }
        //将验证码数据添加到redis
        redisTemplate.opsForValue().set(phone+ RegisterConstant.WXBINDER_CODE_PREFIX,
                code + ":" + System.currentTimeMillis(),3, TimeUnit.MINUTES);//存3分钟
        //发短信
        //SmsUtils.sendSms(phone, "你的验证码为：" + code + "，请在3分钟之内使用!" );
        //测试使用
        System.out.println("你的验证码为：" + code + "，请在3分钟之内使用!");
    }
}
